﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows.Data;
using System.Windows.Input;
using Contracts.Entities;
using Client.Commands;

namespace Client.ViewModels
{
    public class MainViewModel : BaseViewModel
    {
        public static readonly MainViewModel Default = new MainViewModel();

        #region Init

        private ObservableCollection<WorkspaceViewModel> workspaces;
        private string moviesCount;
        private string moviesInserted;

        private const string whitespace = "  ";

        public MainViewModel()
        {
            PlayMovieCommand = new PlayMovieCommand();
            ShowAboutCommand = new ShowAboutCommand();
            ImportWebInfosCommand = new ImportWebInfosCommand();
            SearchMoviesCommand = new SearchMoviesCommand();

            workspaces = new ObservableCollection<WorkspaceViewModel>();
            workspaces.CollectionChanged += this.OnWorkspacesChanged;
            workspaces.Add(AllMoviesViewModel.Default);
            Workspaces.CurrentChanged += Workspaces_CurrentChanged;
        } 

        #endregion

        #region Properties
 
        public ICommand PlayMovieCommand { get; set; }

        public ICommand EditMovieCommand { get; set; }

        public ICommand SaveMovieCommand { get; set; }

        public ICommand LoadMovieCommand { get; set; }

        public ICommand ImportWebInfosCommand { get; set; }

        public ICommand ShowAboutCommand { get; set; }

        public ICommand SearchMoviesCommand { get; set; }

        public string MoviesCount 
        { 
            get 
            {
                return moviesCount;
            } 
            set
            {
                moviesCount = value;
                NotifyPropertyChanged("MoviesCount");
            }
        }

        public string MoviesInserted
        {
            get
            {
                return moviesInserted;
            }
            set
            {
                moviesInserted = value;
                NotifyPropertyChanged("MoviesInserted");
            }
        }

        #endregion

        #region Flow

        public void ImportCompleted(IEnumerable<MovieItem> items)
        {
            ActiveWorkspace.MovieItems = items;
            ActiveWorkspace.IsBusy = false;

            MoviesCount = items.Count().ToString();
            MoviesInserted = items.Where(m => m.SyncState == SyncState.Inserted).Count().ToString();
        } 

        #endregion

        #region Workspaces

        public ICollectionView Workspaces
        {
            get
            {
                return CollectionViewSource.GetDefaultView(workspaces);
            }
        }

        private void OnWorkspacesChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.NewItems)
                    workspace.RequestClose += this.OnWorkspaceRequestClose;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.OldItems)
                    workspace.RequestClose -= this.OnWorkspaceRequestClose;
        }

        private void OnWorkspaceRequestClose(object sender, EventArgs e)
        {
            WorkspaceViewModel workspace = sender as WorkspaceViewModel;
            workspace.Dispose();
            workspaces.Remove(workspace);
        }

        public WorkspaceViewModel ActiveWorkspace
        {
            get
            {
                return Workspaces.CurrentItem as WorkspaceViewModel; 
            }
        }

        private void Workspaces_CurrentChanged(object sender, EventArgs e)
        {
            NotifyPropertyChanged("ActiveWorkspace");
        }

        #endregion

        #region Workspaces Helper

        /// <summary>
        /// Fügt ein editierbaren oder nicht editierbaren Workspace hinzu
        /// oder tauscht diesen aus
        /// </summary>
        public void AddMovieDetailsWorkspace(MovieItem item, bool isEditMode)
        {
            var currentWorkspace = workspaces.SingleOrDefault(m => m.DisplayName == item.Name + whitespace);

            if (currentWorkspace == null)
            {
                WorkspaceViewModel workspace = CreateMovieDetailsWorkspace(item, isEditMode);
                workspaces.Add(workspace);
                Workspaces.MoveCurrentTo(workspace);
            }
            else
            {
                if (!ActiveWorkspace.IsListView || isEditMode)
                    currentWorkspace = ReplaceDetailsWorkspace(item, isEditMode, currentWorkspace);
              
                Workspaces.MoveCurrentTo(currentWorkspace);
            }
        }

        /// <summary>
        /// Tauscht Workspaces an der aktuellen Position
        /// </summary>
        private WorkspaceViewModel ReplaceDetailsWorkspace(MovieItem item, bool isEditMode, WorkspaceViewModel currentWorkspace)
        {
            var pos = Workspaces.CurrentPosition;
            workspaces.Remove(currentWorkspace);
            currentWorkspace = CreateMovieDetailsWorkspace(item, isEditMode);
            workspaces.Insert(pos, currentWorkspace);
            return currentWorkspace;
        }

        private WorkspaceViewModel CreateMovieDetailsWorkspace(MovieItem item, bool isEditMode)
        {
            WorkspaceViewModel workspace = null;

            if (isEditMode)
                workspace = new MovieDetailsEditViewModel();
            else
                workspace = new MovieDetailsViewModel();

            workspace.MovieItem = item;
            workspace.DisplayName = item.Name + whitespace;
            workspace.IsEditMode = isEditMode;

            return workspace;
        }

        /// <summary>
        /// Füt einen Listview mit entsprechendem Request hinzu
        /// </summary>
        public void AddMovieListWorkspace(string request)
        {
            request = request += whitespace;
            var workspace = new MovieListViewModel();
            var currentWorkspace = workspaces.SingleOrDefault(m => m.DisplayName == request);

            if (currentWorkspace != null)
                Workspaces.MoveCurrentTo(currentWorkspace);
            else
            {
                workspace.DisplayName = request;
                workspaces.Add(workspace);
                Workspaces.MoveCurrentTo(workspace);
            }
        } 

        #endregion
    }
}
